use common::serial::api_descriptor::get_wire_type;
use common::serial::api_descriptor::is_array;
use common::serial::api_descriptor::is_map;
use common::serial::api_descriptor::make_tag;
use common::{base::status::Status, serial::api_descriptor::ServiceApiDescriptor};
use protobuf::descriptor::field_descriptor_proto::Type;
use protobuf::descriptor::FieldDescriptorProto;
use protobuf::CodedOutputStream;
use pyo3::prelude::*;
use pyo3::types::{PyDict, PyList, PyType};
use pyo3::PyAny;

fn compute_one_int64_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let number = field.number.unwrap() as u32;

    let i64_value = py_value.extract::<i64>();
    if !i64_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }

    let value = i64_value.unwrap();
    if value == 0 {
        return Ok(0);
    }
    return Ok(protobuf::rt::int64_size(number, value));
}

fn compute_int64_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let mut size = 0;
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            size += compute_one_int64_size(field, ele)?;
        }
        Ok(size)
    } else {
        compute_one_int64_size(field, py_value)
    }
}

fn compute_one_uint64_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let number = field.number.unwrap() as u32;
    let u64_value = py_value.extract::<u64>();
    if !u64_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = u64_value.unwrap();
    if value == 0 {
        return Ok(0);
    }
    return Ok(protobuf::rt::uint64_size(number, value));
}

fn compute_uint64_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let mut size = 0;
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();
        for ele in py_list.iter() {
            size += compute_one_uint64_size(field, ele)?;
        }
        Ok(size)
    } else {
        compute_one_uint64_size(field, py_value)
    }
}
//
fn compute_one_int32_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let number = field.number.unwrap() as u32;
    let i32_value = py_value.extract::<i32>();
    if !i32_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = i32_value.unwrap();
    if value == 0 {
        return Ok(0);
    }
    return Ok(protobuf::rt::int32_size(number, value));
}
//
fn compute_int32_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let mut size = 0;
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();
        for ele in py_list.iter() {
            size += compute_one_int32_size(field, ele)?;
        }
        Ok(size)
    } else {
        compute_one_int32_size(field, py_value)
    }
}
//
fn compute_one_fixed64_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let i64_value = py_value.extract::<i64>();
    if !i64_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = i64_value.unwrap();
    if value == 0 {
        return Ok(0);
    }
    return Ok(1 + 8);
}
//
fn compute_fixed64_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let mut size = 0;
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();
        for ele in py_list.iter() {
            size += compute_one_fixed64_size(field, ele)?;
        }
        Ok(size)
    } else {
        compute_one_fixed64_size(field, py_value)
    }
}
//
fn compute_one_fixed32_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let i32_value = py_value.extract::<i64>();
    if !i32_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = i32_value.unwrap();
    if value == 0 {
        return Ok(0);
    }
    return Ok(1 + 4);
}
//
fn compute_fixed32_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let mut size = 0;
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();
        for ele in py_list.iter() {
            size += compute_one_fixed32_size(field, ele)?;
        }
        Ok(size)
    } else {
        compute_one_fixed32_size(field, py_value)
    }
}
//
fn compute_one_uint32_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let number = field.number.unwrap() as u32;
    let u32_value = py_value.extract::<u32>();
    if !u32_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = u32_value.unwrap();
    if value == 0 {
        return Ok(0);
    }
    return Ok(protobuf::rt::uint32_size(number, value));
}
//
fn compute_uint32_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let mut size = 0;
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();
        for ele in py_list.iter() {
            size += compute_one_uint32_size(field, ele)?;
        }
        Ok(size)
    } else {
        compute_one_uint32_size(field, py_value)
    }
}
//
fn compute_one_enum_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let number = field.number.unwrap() as u32;
    let i32_value = py_value.extract::<i32>();
    if !i32_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = i32_value.unwrap();
    if value == 0 {
        return Ok(0);
    }
    return Ok(protobuf::rt::int32_size(number, value));
}

fn compute_enum_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let mut size = 0;
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();
        for ele in py_list.iter() {
            size += compute_one_enum_size(field, ele)?;
        }
        Ok(size)
    } else {
        compute_one_enum_size(field, py_value)
    }
}
//
//
fn compute_one_sfixed32_size(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
) -> Result<u64, Status> {
    let i32_value = py_value.extract::<i32>();
    if !i32_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = i32_value.unwrap();
    if value == 0 {
        return Ok(0);
    }
    return Ok(1 + 4);
}
//
fn compute_sfixed32_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let mut size = 0;
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();
        for ele in py_list.iter() {
            size += compute_one_sfixed32_size(field, ele)?;
        }
        Ok(size)
    } else {
        compute_one_sfixed32_size(field, py_value)
    }
}
//
fn compute_one_sfixed64_size(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
) -> Result<u64, Status> {
    let i64_value = py_value.extract::<i64>();
    if !i64_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = i64_value.unwrap();
    if value == 0 {
        return Ok(0);
    }
    return Ok(1 + 8);
}
//
fn compute_sfixed64_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let mut size = 0;
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();
        for ele in py_list.iter() {
            size += compute_one_sfixed64_size(field, ele)?;
        }
        Ok(size)
    } else {
        compute_one_sfixed64_size(field, py_value)
    }
}
//
fn compute_one_sint32_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let number = field.number.unwrap() as u32;
    let i32_value = py_value.extract::<i32>();
    if !i32_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = i32_value.unwrap();
    if value == 0 {
        return Ok(0);
    }
    return Ok(protobuf::rt::sint32_size(number, value));
}

//
fn compute_sint32_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let mut size = 0;
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();
        for ele in py_list.iter() {
            size += compute_one_sint32_size(field, ele)?;
        }
        Ok(size)
    } else {
        compute_one_sint32_size(field, py_value)
    }
}
//
fn compute_one_sint64_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let number = field.number.unwrap() as u32;
    let i64_value = py_value.extract::<i64>();
    if !i64_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = i64_value.unwrap();
    if value == 0 {
        return Ok(0);
    }
    return Ok(protobuf::rt::sint64_size(number, value));
}
//
fn compute_sint64_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let mut size = 0;
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();
        for ele in py_list.iter() {
            size += compute_one_sint64_size(field, ele)?;
        }
        Ok(size)
    } else {
        compute_one_sint64_size(field, py_value)
    }
}
//
fn compute_one_double_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let f64_value = py_value.extract::<f64>();
    if !f64_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = f64_value.unwrap();
    if value == 0.0 {
        return Ok(0);
    }
    return Ok(1 + 8);
}
//
fn compute_double_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let mut size = 0;
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();
        for ele in py_list.iter() {
            size += compute_one_double_size(field, ele)?;
        }
        Ok(size)
    } else {
        compute_one_double_size(field, py_value)
    }
}
//
fn compute_one_float_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let f32_value = py_value.extract::<f32>();
    if !f32_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = f32_value.unwrap();
    if value == 0.0 {
        return Ok(0);
    }
    return Ok(1 + 4);
}
//
fn compute_float_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let mut size = 0;
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();
        for ele in py_list.iter() {
            size += compute_one_float_size(field, ele)?;
        }
        Ok(size)
    } else {
        compute_one_float_size(field, py_value)
    }
}
//
fn compute_one_string_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let str_value = py_value.extract::<&str>();
    if !str_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = str_value.unwrap();
    if value.is_empty() {
        return Ok(0);
    }
    let number = field.number.unwrap() as u32;
    Ok(protobuf::rt::string_size(number, value))
}
//
fn compute_string_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let mut size = 0;
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();
        for ele in py_list.iter() {
            size += compute_one_string_size(field, ele)?;
        }
        Ok(size)
    } else {
        compute_one_string_size(field, py_value)
    }
}
//
fn compute_one_bool_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let bool_value = py_value.extract::<bool>();
    if !bool_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = bool_value.unwrap();
    if value == false {
        return Ok(0);
    }
    return Ok(2 + 1);
}
//
fn compute_bool_size(field: &FieldDescriptorProto, py_value: &PyAny) -> Result<u64, Status> {
    let mut size = 0;
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();
        for ele in py_list.iter() {
            size += compute_one_bool_size(field, ele)?;
        }
        Ok(size)
    } else {
        compute_one_bool_size(field, py_value)
    }
}
//
fn compute_object_size(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    service_api_descriptor: &ServiceApiDescriptor,
    py_type: &PyType,
) -> Result<u64, Status> {
    if field.type_name.is_none() {
        return Err(Status::error(format!(
            "{} 类型错误, 应为数组！",
            field.name.as_ref().unwrap()
        )));
    }
    let type_name = field.type_name.as_ref().unwrap();
    let mut size = 0;
    //
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        //
        let py_list = py_list.unwrap();
        for ele in py_list.iter() {
            let len = compute_size(ele, &type_name, service_api_descriptor, py_type)?;
            size += 1 + protobuf::rt::compute_raw_varint64_size(len) + len;
        }
    } else {
        let len = compute_size(py_value, type_name, service_api_descriptor, py_type)?;
        size = 1 + protobuf::rt::compute_raw_varint64_size(len) + len;
    }
    Ok(size)
}
//
fn compute_size_inner(
    field_type: Type,
    field: &FieldDescriptorProto,
    service_api_descriptor: &ServiceApiDescriptor,
    py_value: &PyAny,
    py_type: &PyType,
) -> Result<u64, Status> {
    match field_type {
        // i64
        Type::TYPE_INT64 => compute_int64_size(field, py_value),
        // ui64
        Type::TYPE_UINT64 => compute_uint64_size(field, py_value),
        // i32
        Type::TYPE_INT32 => compute_int32_size(field, py_value),
        // fixed64
        Type::TYPE_FIXED64 => compute_fixed64_size(field, py_value),
        // fixed32
        Type::TYPE_FIXED32 => compute_fixed32_size(field, py_value),
        // u32
        Type::TYPE_UINT32 => compute_uint32_size(field, py_value),
        // enum
        Type::TYPE_ENUM => compute_enum_size(field, py_value),
        // sfixed32
        Type::TYPE_SFIXED32 => compute_sfixed32_size(field, py_value),
        // sfixed64
        Type::TYPE_SFIXED64 => compute_sfixed64_size(field, py_value),
        // sint32
        Type::TYPE_SINT32 => compute_sint32_size(field, py_value),
        // sint64
        Type::TYPE_SINT64 => compute_sint64_size(field, py_value),
        // double
        Type::TYPE_DOUBLE => compute_double_size(field, py_value),
        //
        Type::TYPE_FLOAT => compute_float_size(field, py_value),
        //
        Type::TYPE_STRING => compute_string_size(field, py_value),
        // 对象
        Type::TYPE_MESSAGE => compute_object_size(field, py_value, service_api_descriptor, py_type),
        // 对象
        Type::TYPE_BOOL => compute_bool_size(field, py_value),
        //
        _ => {
            return Err(Status::error(format!("无消息 描述信息！")));
        }
    }
}

pub fn compute_size(
    py_obj: &PyAny,
    msg_name: &str,
    service_api_descriptor: &ServiceApiDescriptor,
    py_type: &PyType,
) -> Result<u64, Status> {
    let mut buffer_size = 0;

    let message_descriptor_holder = service_api_descriptor
        .message_descriptor_holder
        .get(msg_name);

    if message_descriptor_holder.is_none() {
        return Err(Status::error(format!("无消息：{} 描述信息！", msg_name)));
    }
    let msg_descriptor = &message_descriptor_holder.unwrap().descriptor_proto;
    for field in &msg_descriptor.field {
        let field_name = field.name.as_ref().unwrap();
        let py_value = py_obj.getattr(field_name.as_str());

        if py_value.is_err() {
            continue;
        }
        let py_value = py_value.unwrap();
        let field_type = field.type_.unwrap().unwrap();
        if field_type == Type::TYPE_MESSAGE && is_map(field, service_api_descriptor) {
            let ret = py_type.is_instance(py_value);
            if ret.is_err() {
                return Err(Status::error(format!("{} 类型错误，应为 obj", msg_name)));
            }

            let map_type_name = field.type_name.as_ref().unwrap();
            let map_msg_descriptor_holder = service_api_descriptor
                .message_descriptor_holder
                .get(map_type_name);

            let message_descriptor = &map_msg_descriptor_holder.unwrap().descriptor_proto;

            let key_field = message_descriptor.field.get(0).unwrap();

            let value_field = message_descriptor.field.get(1).unwrap();

            let key_field_type = key_field.type_.unwrap().unwrap();

            let value_field_type = value_field.type_.unwrap().unwrap();
            //

            let dict_value = py_value.downcast::<PyDict>();
            if dict_value.is_err() {
                return Err(Status::error(format!("{} 类型错误，应为 Dict", msg_name)));
            }
            let dict_value = dict_value.unwrap();

            for (key, value) in dict_value.iter() {
                let mut entry_size = 0;
                entry_size += compute_size_inner(
                    key_field_type,
                    key_field,
                    service_api_descriptor,
                    key,
                    py_type,
                )?;

                entry_size += compute_size_inner(
                    value_field_type,
                    value_field,
                    service_api_descriptor,
                    value,
                    py_type,
                )?;
                buffer_size +=
                    2 + ::protobuf::rt::compute_raw_varint64_size(entry_size) + entry_size;
            }
        } else {
            buffer_size +=
                compute_size_inner(field_type, field, service_api_descriptor, py_value, py_type)?;

            // println!(
            //     "field_name = {}  compute temp size = {}",
            //     field_name, buffer_size
            // );
        }
    }

    Ok(buffer_size)
}
//
fn write_one_int64(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let number = field.number.unwrap() as u32;
    let i64_value = py_value.extract::<i64>();
    if !i64_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }

    let value = i64_value.unwrap();
    if value == 0 {
        return Ok(());
    }
    let result = output_stream.write_int64(number, value);
    if result.is_err() {
        return Err(Status::error(format!(
            "{} 序列化失败！",
            field.name.as_ref().unwrap()
        )));
    }
    Ok(())
}

//
fn write_int64(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            write_one_int64(field, ele, output_stream)?;
        }
        Ok(())
    } else {
        write_one_int64(field, py_value, output_stream)
    }
}
//
fn write_one_uint64(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let number = field.number.unwrap() as u32;
    let u64_value = py_value.extract::<u64>();
    if !u64_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }

    let value = u64_value.unwrap();
    if value == 0 {
        return Ok(());
    }
    let result = output_stream.write_uint64(number, value);
    if result.is_err() {
        return Err(Status::error(format!(
            "{} 序列化失败！",
            field.name.as_ref().unwrap()
        )));
    }
    Ok(())
}
//
fn write_uint64(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            write_one_uint64(field, ele, output_stream)?;
        }
        Ok(())
    } else {
        write_one_uint64(field, py_value, output_stream)
    }
}

//
fn write_one_int32(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let number = field.number.unwrap() as u32;
    let i32_value = py_value.extract::<i32>();
    if !i32_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }

    let value = i32_value.unwrap();
    if value == 0 {
        return Ok(());
    }
    let result = output_stream.write_int32(number, value);
    if result.is_err() {
        return Err(Status::error(format!(
            "{} 序列化失败！",
            field.name.as_ref().unwrap()
        )));
    }
    Ok(())
}

//
fn write_int32(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            write_one_int32(field, ele, output_stream)?;
        }
        Ok(())
    } else {
        write_one_int32(field, py_value, output_stream)
    }
}
//
fn write_one_fixed64(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let number = field.number.unwrap() as u32;
    let u64_value = py_value.extract::<u64>();
    if !u64_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = u64_value.unwrap();
    if value == 0 {
        return Ok(());
    }
    let result = output_stream.write_fixed64(number, value);
    if result.is_err() {
        return Err(Status::error(format!(
            "{} 序列化失败！",
            field.name.as_ref().unwrap()
        )));
    }
    Ok(())
}
//
fn write_fixed64(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            write_one_fixed64(field, ele, output_stream)?;
        }
        Ok(())
    } else {
        write_one_fixed64(field, py_value, output_stream)
    }
}
//
fn write_one_fixed32(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let number = field.number.unwrap() as u32;
    let u32_value = py_value.extract::<u32>();
    if !u32_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = u32_value.unwrap();
    if value == 0 {
        return Ok(());
    }
    let result = output_stream.write_fixed32(number, value);
    if result.is_err() {
        return Err(Status::error(format!(
            "{} 序列化失败！",
            field.name.as_ref().unwrap()
        )));
    }
    Ok(())
}
//
fn write_fixed32(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            write_one_fixed32(field, ele, output_stream)?;
        }
        Ok(())
    } else {
        write_one_fixed32(field, py_value, output_stream)
    }
}
//
fn write_one_uint32(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let number = field.number.unwrap() as u32;
    let u32_value = py_value.extract::<u32>();
    if !u32_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = u32_value.unwrap();
    if value == 0 {
        return Ok(());
    }
    let result = output_stream.write_uint32(number, value);
    if result.is_err() {
        return Err(Status::error(format!(
            "{} 序列化失败！",
            field.name.as_ref().unwrap()
        )));
    }
    Ok(())
}
//
fn write_uint32(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            write_one_uint32(field, ele, output_stream)?;
        }
        Ok(())
    } else {
        write_one_uint32(field, py_value, output_stream)
    }
}
//
fn write_one_enum(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let number = field.number.unwrap() as u32;
    let i32_value = py_value.extract::<i32>();
    if !i32_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = i32_value.unwrap();
    if value == 0 {
        return Ok(());
    }
    let result = output_stream.write_enum(number, value);
    if result.is_err() {
        return Err(Status::error(format!(
            "{} 序列化失败！",
            field.name.as_ref().unwrap()
        )));
    }
    Ok(())
}
//
fn write_enum(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            write_one_enum(field, ele, output_stream)?;
        }
        Ok(())
    } else {
        write_one_enum(field, py_value, output_stream)
    }
}
//
fn write_one_sfixed32(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let number = field.number.unwrap() as u32;
    let i32_value = py_value.extract::<i32>();
    if !i32_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = i32_value.unwrap();
    if value == 0 {
        return Ok(());
    }
    let result = output_stream.write_sfixed32(number, value);
    if result.is_err() {
        return Err(Status::error(format!(
            "{} 序列化失败！",
            field.name.as_ref().unwrap()
        )));
    }
    Ok(())
}
//
fn write_sfixed32(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            write_one_sfixed32(field, ele, output_stream)?;
        }
        Ok(())
    } else {
        write_one_sfixed32(field, py_value, output_stream)
    }
}
//
fn write_one_sfixed64(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let number = field.number.unwrap() as u32;
    let i64_value = py_value.extract::<i64>();
    if !i64_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = i64_value.unwrap();
    if value == 0 {
        return Ok(());
    }
    let result = output_stream.write_sfixed64(number, value);
    if result.is_err() {
        return Err(Status::error(format!(
            "{} 序列化失败！",
            field.name.as_ref().unwrap()
        )));
    }
    Ok(())
}
//
fn write_sfixed64(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            write_one_sfixed64(field, ele, output_stream)?;
        }
        Ok(())
    } else {
        write_one_sfixed64(field, py_value, output_stream)
    }
}
//
fn write_one_sint32(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let number = field.number.unwrap() as u32;
    let i32_value = py_value.extract::<i32>();
    if !i32_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = i32_value.unwrap();
    if value == 0 {
        return Ok(());
    }
    let result = output_stream.write_sint32(number, value);
    if result.is_err() {
        return Err(Status::error(format!(
            "{} 序列化失败！",
            field.name.as_ref().unwrap()
        )));
    }
    Ok(())
}
//
fn write_sint32(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            write_one_sint32(field, ele, output_stream)?;
        }
        Ok(())
    } else {
        write_one_sint32(field, py_value, output_stream)
    }
}

//
fn write_one_sint64(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let number = field.number.unwrap() as u32;
    let i64_value = py_value.extract::<i64>();
    if !i64_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = i64_value.unwrap();
    if value == 0 {
        return Ok(());
    }
    let result = output_stream.write_sint64(number, value);
    if result.is_err() {
        return Err(Status::error(format!(
            "{} 序列化失败！",
            field.name.as_ref().unwrap()
        )));
    }
    Ok(())
}
//
fn write_sint64(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            write_one_sint64(field, ele, output_stream)?;
        }
        Ok(())
    } else {
        write_one_sint64(field, py_value, output_stream)
    }
}
//
fn write_one_double(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let number = field.number.unwrap() as u32;
    let f64_value = py_value.extract::<f64>();
    if !f64_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = f64_value.unwrap();
    if value == 0.0 {
        return Ok(());
    }
    let result = output_stream.write_double(number, value);
    if result.is_err() {
        return Err(Status::error(format!(
            "{} 序列化失败！",
            field.name.as_ref().unwrap()
        )));
    }
    Ok(())
}
//
fn write_double(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            write_one_double(field, ele, output_stream)?;
        }
        Ok(())
    } else {
        write_one_double(field, py_value, output_stream)
    }
}
//

fn write_one_float(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let number = field.number.unwrap() as u32;
    let f32_value = py_value.extract::<f32>();
    if !f32_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = f32_value.unwrap();
    if value == 0.0 {
        return Ok(());
    }
    let result = output_stream.write_float(number, value);
    if result.is_err() {
        return Err(Status::error(format!(
            "{} 序列化失败！",
            field.name.as_ref().unwrap()
        )));
    }
    Ok(())
}
//
fn write_float(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            write_one_float(field, ele, output_stream)?;
        }
        Ok(())
    } else {
        write_one_float(field, py_value, output_stream)
    }
}
//
fn write_one_string(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let number = field.number.unwrap() as u32;
    let str_value = py_value.extract::<&str>();
    if !str_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = str_value.unwrap();
    if value.is_empty() {
        return Ok(());
    }
    // println!("str = {}", value);
    let result = output_stream.write_string(number, value);
    if result.is_err() {
        return Err(Status::error(format!(
            "{} 序列化失败！",
            field.name.as_ref().unwrap()
        )));
    }
    Ok(())
}
//
fn write_string(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            write_one_string(field, ele, output_stream)?;
        }
        Ok(())
    } else {
        write_one_string(field, py_value, output_stream)
    }
}
//
//
fn write_one_bool(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let number = field.number.unwrap() as u32;
    let bool_value = py_value.extract::<bool>();
    if !bool_value.is_ok() {
        return Err(Status::error(format!(
            "{} 类型错误！",
            field.name.as_ref().unwrap()
        )));
    }
    let value = bool_value.unwrap();
    if value == false {
        return Ok(());
    }
    let result = output_stream.write_bool(number, value);
    if result.is_err() {
        return Err(Status::error(format!(
            "{} 序列化失败！",
            field.name.as_ref().unwrap()
        )));
    }
    Ok(())
}
//
fn write_bool(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();

        for ele in py_list.iter() {
            write_one_bool(field, ele, output_stream)?;
        }
        Ok(())
    } else {
        write_one_bool(field, py_value, output_stream)
    }
}
//
fn write_object(
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    service_api_descriptor: &ServiceApiDescriptor,
    py_type: &PyType,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let type_name = field.type_name.as_ref().unwrap();
    if is_array(field) {
        let py_list = py_value.downcast::<PyList>();
        if !py_list.is_ok() {
            return Err(Status::error(format!(
                "{} 类型错误, 应为数组！",
                field.name.as_ref().unwrap()
            )));
        }
        let py_list = py_list.unwrap();
        let number = field.number.unwrap() as u32;
        for ele in py_list.iter() {
            output_stream
                .write_tag(number, protobuf::rt::WireType::LengthDelimited)
                .unwrap();
            let len = compute_size(ele, type_name, service_api_descriptor, py_type)?;
            output_stream.write_raw_varint32(len as u32).unwrap();

            pyobj_to_proto_with_buffer(
                ele,
                type_name,
                service_api_descriptor,
                py_type,
                output_stream,
            )?;
        }
        Ok(())
    } else {
        //
        let number = field.number.unwrap() as u32;
        output_stream
            .write_tag(number, protobuf::rt::WireType::LengthDelimited)
            .unwrap();
        let len = compute_size(py_value, type_name, service_api_descriptor, py_type)?;
        output_stream.write_raw_varint32(len as u32).unwrap();
        pyobj_to_proto_with_buffer(
            py_value,
            type_name,
            service_api_descriptor,
            py_type,
            output_stream,
        )
    }
}
//

fn pyobj_to_proto_with_buffer_inner(
    field_type: Type,
    field: &FieldDescriptorProto,
    py_value: &PyAny,
    service_api_descriptor: &ServiceApiDescriptor,
    py_type: &PyType,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    match field_type {
        // i64
        Type::TYPE_INT64 => write_int64(field, py_value, output_stream),
        // ui64
        Type::TYPE_UINT64 => write_uint64(field, py_value, output_stream),
        // i32
        Type::TYPE_INT32 => write_int32(field, py_value, output_stream),
        // fixed64
        Type::TYPE_FIXED64 => write_fixed64(field, py_value, output_stream),
        // fixed32
        Type::TYPE_FIXED32 => write_fixed32(field, py_value, output_stream),
        // u32
        Type::TYPE_UINT32 => write_uint32(field, py_value, output_stream),
        // enum
        Type::TYPE_ENUM => write_enum(field, py_value, output_stream),
        // sfixed32
        Type::TYPE_SFIXED32 => write_sfixed32(field, py_value, output_stream),
        // sfixed64
        Type::TYPE_SFIXED64 => write_sfixed64(field, py_value, output_stream),
        // sint32
        Type::TYPE_SINT32 => write_sint32(field, py_value, output_stream),
        // sint64
        Type::TYPE_SINT64 => write_sint64(field, py_value, output_stream),
        // double
        Type::TYPE_DOUBLE => write_double(field, py_value, output_stream),
        //
        Type::TYPE_FLOAT => write_float(field, py_value, output_stream),
        //
        Type::TYPE_STRING => write_string(field, py_value, output_stream),
        // 对象
        Type::TYPE_MESSAGE => write_object(
            field,
            py_value,
            service_api_descriptor,
            py_type,
            output_stream,
        ),
        // 对象
        Type::TYPE_BOOL => write_bool(field, py_value, output_stream),
        //
        _ => Err(Status::error("类型错误！".into())),
    }
}

pub fn pyobj_to_proto_with_buffer(
    py_obj: &PyAny,
    msg_name: &str,
    service_api_descriptor: &ServiceApiDescriptor,
    py_type: &PyType,
    output_stream: &mut CodedOutputStream,
) -> Result<(), Status> {
    let msg_descriptor_holder = service_api_descriptor
        .message_descriptor_holder
        .get(msg_name);

    let msg_descriptor = &msg_descriptor_holder.unwrap().descriptor_proto;

    for field in &msg_descriptor.field {
        let field_name = field.name.as_ref().unwrap();
        let py_value = py_obj.getattr(field_name.as_str());

        if py_value.is_err() {
            continue;
        }
        let py_value = py_value.unwrap();
        let field_type = field.type_.unwrap().unwrap();
        //
        if field_type == Type::TYPE_MESSAGE && is_map(field, service_api_descriptor) {
            let map_type_name = field.type_name.as_ref().unwrap();

            let map_msg_descriptor_holder = service_api_descriptor
                .message_descriptor_holder
                .get(map_type_name);
            //
            let message_descriptor = &map_msg_descriptor_holder.unwrap().descriptor_proto;

            let key_field = message_descriptor.field.get(0).unwrap();

            let value_field = message_descriptor.field.get(1).unwrap();

            let key_field_type = key_field.type_.unwrap().unwrap();

            let value_field_type = value_field.type_.unwrap().unwrap();
            //
            let dict_value = py_value.downcast::<PyDict>();
            if dict_value.is_err() {
                return Err(Status::error(format!("{} 类型错误，应为 Dict", msg_name)));
            }
            let dict_value = dict_value.unwrap();
            //

            let number = field.number() as u32;

            let wire_type = get_wire_type(field);

            let tag = make_tag(number, wire_type);

            for (key, value) in dict_value.iter() {
                let mut entry_size = 0;

                entry_size += compute_size_inner(
                    key_field_type,
                    key_field,
                    service_api_descriptor,
                    key,
                    py_type,
                )?;

                entry_size += compute_size_inner(
                    value_field_type,
                    value_field,
                    service_api_descriptor,
                    value,
                    py_type,
                )?;
                //
                output_stream.write_raw_varint32(tag).unwrap();
                output_stream.write_raw_varint32(entry_size as u32).unwrap();
                //

                pyobj_to_proto_with_buffer_inner(
                    field_type,
                    field,
                    key,
                    service_api_descriptor,
                    py_type,
                    output_stream,
                )?;

                //

                pyobj_to_proto_with_buffer_inner(
                    field_type,
                    field,
                    value,
                    service_api_descriptor,
                    py_type,
                    output_stream,
                )?;
            }
            //
        } else {
            pyobj_to_proto_with_buffer_inner(
                field_type,
                field,
                py_value,
                service_api_descriptor,
                py_type,
                output_stream,
            )?;
        }
        // println!(
        //     "field_name = {}  write temp size = {}",
        //     field_name,
        //     output_stream.total_bytes_written()
        // );
    }

    Ok(())
}
//



pub fn pyobj_to_proto(
    py_obj: &PyAny,
    msg_name: &str,
    service_api_descriptor: &ServiceApiDescriptor,
    py_type: &PyType,
) -> Result<Vec<u8>, Status> {
    let buffer_size = compute_size(py_obj, msg_name, service_api_descriptor, py_type)?;

    let mut buffer = Vec::with_capacity(buffer_size as usize);

    let mut output_stream = CodedOutputStream::vec(&mut buffer);
    //
    pyobj_to_proto_with_buffer(
        py_obj,
        msg_name,
        service_api_descriptor,
        py_type,
        &mut output_stream,
    )?;
    let flush_result = output_stream.flush();
    if flush_result.is_err() {
        return Err(Status::error(flush_result.err().unwrap().to_string()));
    }
    drop(output_stream);

    // println!("buffer_size = {}, vec_size = {}", buffer_size, buffer.len());

    Ok(buffer)
}
